/* MolShape.m - Copyright 1993  Steve Ludtke */
/* This object does the actual molecule rendering (except for quick mode) */
/* ball and stick mode is still quite primitive */
/* I should probably change the flags from numbers to #defined strings ... */
#import "Mtypes.h"
#import "MolShape.h"
#import <ri/ri.h>
#import <math.h>

#define SC .05
#define SCP1 SC/1.732
#define SCP2 SC/.866
#define SCP3 SC/2.45
#define SCP4 SC/1.633-SCP3

@implementation MolShape:N3DShape
- renderSelf:(RtToken)context
{
int i,j,n,ln;
float x,y,z,r,lx,ly,lz;
/* a big square for a white background */
static RtPoint bsquare[4]= {{-200.0,-200.0,-40.0},{200.0,-200.0,-40.0},{200.0,200.0,-40.0},{-200.0,200.0,-40.0}};
static RtColor bgCol = {1.0,1.0,1.0};
static RtColor bCol = { 0,0,0 };
static RtColor dCol = { 1.0,1.0,1.0 };
static RtColor selCol = { 0.0,0.0,0.0 };

if (mode==4) return self;	/* quick mode, do nothing */
if (mode==12) mode=11;		/* quick mode, but we want to print, so render */

RiSurface("constant",RI_NULL);
if (mode>=8) {
	RiColor(bgCol);
	RiPolygon(4,RI_P,(RtPointer)bsquare,RI_NULL);
}
RiRotate(chi,0,1.0,0);
RiRotate(theta,1.0,0,0.0);
RiRotate(phi,0,1.0,0);

/* metal is ok too ... */
RiSurface("plastic",RI_NULL);
RiColor(dCol);

/* stick mode */
if ((flags&3)==0) {
	RiColor(bCol);
	for (i=0; i<nmol; i++) {
		ln=-1;
		if (mol[i].numlb==0) continue;
		RiPointsLines(mol[i].numlb,mol[i].nverts,mol[i].verts
				,RI_P,mol[i].coord,RI_NULL);
	}
}
/* ball and stick mode, ball size ratio hardcoded */
else if ((flags&3)==1) {
	for (i=0; i<nmol; i++) {
		if ((mode&3)>=2) RiColor(dCol);
		else RiColor(dCol);
		ln=-1;
		for (j=0; j<mol[i].numa; j++) {
			x=mol[i].coord[j][0];
			y=mol[i].coord[j][1];
			z=mol[i].coord[j][2];
			n=mol[i].atom[j].anum;
			r=elinfo[n].rad/3.0;
			if (n!=ln) RiColor(elinfo[n].color);
			ln=n;
			RiTransformBegin();
			RiTranslate(x,y,z);
			RiSphere(r,-r,r,360.0,RI_NULL);
			RiTransformEnd();			 
		}
		RiColor(bCol);
		RiPointsLines(mol[i].numlb,mol[i].nverts,mol[i].verts
				,RI_P,mol[i].coord,RI_NULL);
	}
}
/* space filling mode */
else if ((flags&3)==2) {
	lx=ly=lz=0;
	for (i=0; i<nmol; i++) {
		if ((mode&3)>=2) RiColor(dCol);
		else RiColor(dCol);
		ln=-1;
		for (j=0; j<mol[i].numa; j++) {
			x=mol[i].coord[j][0];
			y=mol[i].coord[j][1];
			z=mol[i].coord[j][2];
			n=mol[i].atom[j].anum;
			r=elinfo[n].rad;
			if (n!=ln) RiColor(elinfo[n].color);
			ln=n;
			if (mol[i].atom[j].sel) { RiColor(selCol); ln=-1; }
			RiTranslate(x-lx,y-ly,z-lz);
			RiSphere(r,-r,r,360.0,RI_NULL);
			if (r==0.0) printf("%d %d  %f %f %f\n",j,n,x,y,z);
			lx=x; ly=y; lz=z;	 
		}
	}
}
return self;
}

-setData:(Molecule *)Mol :(int)Nmol :(struct ELINFO *)Elinfo :(int)Mode :(int)Flags
{
mol=Mol;
nmol=Nmol;
elinfo=Elinfo;
mode=Mode;
flags=Flags;
return self;
}

-setAng:(float)Theta :(float)Chi :(float)Phi
{
theta=Theta/DRC;
chi=Chi/DRC;
phi=Phi/DRC;
return self;
}

- setSurfaceType:(N3DSurfaceType)st andDescendants:(BOOL)flag
{
[super setSurfaceType:st andDescendants:flag];
return self;
}

@end
  
